
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Tracker {
    public static int trackerPort=6000;
    // 服务器节点个数
    public static List<Node> list = new ArrayList<>();
    // 区域范围
    public static List<Integer> minList = new ArrayList<>();
    public static List<Integer> maxList = new ArrayList<>();

    public static void main(String[] args) {
        System.out.println("Tracker启动了");
        //读取配置文件
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(new File("src/config.txt")));
            String s = br.readLine();//第一行作为注释
            s = br.readLine();
            while (s != null && !s.equals("")) {
                String[] s1 = s.split(" ");
                try {
                    list.add(new Node(s1[0], s1[1], s1[2]));
                } catch (Exception e) {
                    //如果解析错误，解析下一个
                    System.out.println("解析配置文件失败,请检查配置文件，第一行为注释，以下为配置");
                    break;
                }

                s = br.readLine();
            }
            br.close();
        } catch (FileNotFoundException e) {
            System.out.println("找不到配置文件");
        } catch (IOException e) {
            System.out.println("读取配置文件失败");
        }

        for (int i = 0; i < list.size(); i++) {
            minList.add((99 / list.size()) * i);
            if (i == list.size() - 1) {
                maxList.add(99);
            } else {
                maxList.add((99 / list.size()) * (i + 1) - 1);
            }
        }


        DatagramSocket ds = null;
        try {
            ds = new DatagramSocket(trackerPort);
        } catch (Exception e) {
            System.out.println("Tracker的udp服务出现异常");
            return;
        }
        System.out.println(minList);
        System.out.println(maxList);
        while (true) {
            try {
                byte[] data = new byte[1024];
                DatagramPacket dp = new DatagramPacket(data, data.length);

                ds.receive(dp);

                //根据data的内容   返回相应的内容bytes
                byte[] bytes = null;
                if (data[0] == 0)//STORAGE_LOCATION_REQUEST 客户端发送消息给tracker，请求指定玩家所对应的服务器的地址
                {
                    System.out.println("接收到STORAGE_LOCATION_REQUEST");
                    String reqName = new String(Arrays.copyOfRange(data, 5, 15)).trim();

                    bytes = new byte[14];
                    bytes[0] = 1;//msgType

                    bytes[1] = data[1];//唯一id
                    bytes[2] = data[2];
                    bytes[3] = data[3];
                    bytes[4] = data[4];


                    Node node = list.get(hash(reqName));


                    String[] split = node.ip.split("\\.");
                    bytes[5] = Byte.parseByte(split[0]);
                    bytes[6] = Byte.parseByte(split[1]);
                    bytes[7] = Byte.parseByte(split[2]);
                    bytes[8] = Byte.parseByte(split[3]);

                    int count = 9;
                    byte[] bytes1 = toBytes(Integer.parseInt(node.udpPort));
                    for (byte b : bytes1) {
                        bytes[count++] = b;
                    }
                } else if (data[0] == 2)//SERVER_AREA_REQUEST客户机向tracker发送请求以获得某个位置所对应的服务器
                {
                    System.out.println("接收到SERVER_AREA_REQUEST");
                    int x = data[5];
                    int y = data[6];

                    bytes = new byte[16];
                    bytes[0] = 3;//msgType

                    bytes[1] = data[1];//唯一id
                    bytes[2] = data[2];
                    bytes[3] = data[3];
                    bytes[4] = data[4];

                    //求serverID来获得xy的界限
                    int serverID = 0;
                    for (int i = 0; i < list.size(); i++) {
                        if (minList.get(i) <= x && x <= maxList.get(i)) {
                            serverID = i;
                            break;
                        }
                    }


                    String[] split = list.get(serverID).ip.split("\\.");
                    bytes[5] = Byte.parseByte(split[0]);
                    bytes[6] = Byte.parseByte(split[1]);
                    bytes[7] = Byte.parseByte(split[2]);
                    bytes[8] = Byte.parseByte(split[3]);

                    byte[] bytes3 = toBytes(Integer.parseInt(list.get(serverID).tcpPort));

                    bytes[9] = bytes3[2];
                    bytes[10] = bytes3[3];

                    bytes[11] = minList.get(serverID).byteValue();
                    bytes[12] = maxList.get(serverID).byteValue();
                    bytes[13] = 0;
                    bytes[14] = 99;

                    bytes[15] = 0;


                } else {
                    System.out.println("收到类型无效的消息");
                    continue;
                }

                DatagramPacket Sendpacket = new DatagramPacket(bytes, bytes.length, dp.getAddress(), dp.getPort());
                ds.send(Sendpacket);
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("udp出错了一次");
            }
        }

    }

    public static int hash(String name) {
        int res = 0;
        byte[] bytes = name.getBytes();
        for (byte b : bytes) {
            res = b + 31 * res;
        }
        return res % list.size();
    }

    public static class Node {
        public String ip;
        public String tcpPort;
        public String udpPort;

        public Node(String ip, String tcpPort, String udpPort) {
            this.ip = ip;
            this.tcpPort = tcpPort;
            this.udpPort = udpPort;
        }
    }


    public static byte[] toBytes(int a) {
        byte[] temp = new byte[4];
        temp[0] = (byte) (a >> 24);
        temp[1] = (byte) (a >> 16);
        temp[2] = (byte) (a >> 8);
        temp[3] = (byte) a;
        return temp;
    }

}
